package com.fessc.develop.handler.processor.callback;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fessc.develop.base.Result;
import com.fessc.develop.entity.comvo.PaymentCallBackBodyVo;
import com.fessc.develop.entity.comvo.PaymentCallBackVo;
import com.fessc.develop.entity.dbvo.SettleTrade;
import com.fessc.develop.model.enums.EnumCallBackOption;
import com.fessc.develop.model.enums.EnumJsonProperty;
import com.fessc.develop.model.enums.EnumPaymentStatus;
import com.fessc.develop.model.enums.EnumResultType;
import com.fessc.develop.service.interfaces.ISettleTradeListService;
import com.fessc.develop.service.interfaces.ISettleTradeService;
import com.fessc.develop.utils.BusiUtil;
import com.fessc.develop.utils.DateUtil;
import com.fessc.develop.utils.ErrorUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;

@Slf4j
@Service
public class SettleTradeCallBackProcessor implements ICallBackProcessor {

    @Resource
    private ISettleTradeService settleTradeService;

    @Resource
    private ISettleTradeListService settleTradeListService;

    @Override
    public String getOption() {
        return EnumCallBackOption.SETTLE_TRADE_CALL_BACK.toString();
    }

    /**
     * 跨境付汇交易结果回调
     *
     * @param bankCallBackVo 跨境付汇交易结果回调报文
     * @return 返回结果
     */
    @Override
    public Result process(PaymentCallBackVo bankCallBackVo) {
        log.info("跨境付汇回调通知处理开始");
        Result result = new Result(EnumResultType.SUCCESS.getStatusCode(), EnumResultType.SUCCESS.getMsg());
        List<PaymentCallBackBodyVo> ordrNos = bankCallBackVo.getSubArray();

        //判断订单编号、业务类型、交易结果是否为空，是否符合报文要求
        String errorCode = check(bankCallBackVo);
        if (BusiUtil.isNotNull(errorCode)) {
            JSONObject jsonDate = new JSONObject();
            jsonDate.put(EnumJsonProperty.RES_PCSGRLT.toString(), "01");
            jsonDate.put(EnumJsonProperty.RES_FALRS.toString(), ErrorUtil.getErrorDesc(errorCode));
            result.setData(jsonDate);
            return result;
        }

        List<PaymentCallBackBodyVo> settleTradeList = bankCallBackVo.getSubArray();
        // 组织参数批量更新
        for (PaymentCallBackBodyVo callBackBodyVo : settleTradeList) {
            // 查询订单号是否存在
            SettleTrade settleTrade = settleTradeService.getSettleTradeBySettleId(callBackBodyVo.getOrderNo());

            if (BusiUtil.isNull(settleTrade)) {
                log.info("跨境付汇订单号不存在：" + callBackBodyVo.getOrderNo());
            } else if (BusiUtil.isNotNull(settleTrade) && BusiUtil.isEquals(callBackBodyVo.getStatus(), EnumResultType.COM_TRAN_STATUS_SUCCESS.getStatusCode())) {
                log.info("跨境付汇交易状态查询返回交易成功，修改状态为成功：" + settleTrade.getSettleId());
                // 将review_status更改为2，deal_date为当前时间，deal_performer为银行直连机构号，review_date为当前时间
                // 将review_performer为银行直连机构号，send2更改为N，serialnumber更改实际的跨境付款流水号
                settleTrade.setReviewStatus(EnumPaymentStatus.SETTLE_REVIEW_SUCCESS.toString()); //银行审核付款成功
                settleTrade.setDealDate(DateUtil.getCurrentLocalDateTime());  //当前时间
                settleTrade.setDealPerformer(settleTrade.getOrgCode()); //银行直连机构号
                settleTrade.setReviewDate(DateUtil.getCurrentLocalDateTime());  //当前时间
                settleTrade.setReviewPerformer(settleTrade.getOrgCode());  //银行直连机构号
                settleTrade.setSerialnumber(settleTrade.getSettleId());  //没有汇总订单的付款流水号，用settle_id代替
                settleTrade.setSend2(EnumPaymentStatus.SETTLE_CANCEL_SEND.toString());

                // 更新跨境订单交易表
                log.info("更新跨境付汇订单状态为成功：" + settleTrade.getSettleId());
                settleTradeService.updateSettleTradeStatusRefidsLog(settleTrade, EnumPaymentStatus.PAYMENT_SUCCESS.toString()); //更新交易成功状态

                // 更新跨境订单明细表
                log.info("更新跨境付订单汇明细状态为已跨境付汇：" + settleTrade.getSettleId());
                settleTradeListService.updateSettleTradeListStatus(settleTrade.getSettleId(), "Y");

            } else if (BusiUtil.isNotNull(settleTrade) && BusiUtil.isEquals(callBackBodyVo.getStatus(), EnumResultType.COM_TRAN_STATUS_FAIL.getStatusCode())) {
                log.info("跨境付汇交易状态查询返回交易失败，修改状态为成功：" + settleTrade.getSettleId());
                // 将 review_status 更改为 3，reject_date 为当前时间，reject_performer 为银行直连机构号
                // 将 remark 更改为银行返回的失败原因，cancel_send 更改为 N
                settleTrade.setReviewStatus(EnumPaymentStatus.SETTLE_REVIEW_FAIL.toString()); //银行审核付款失败
                settleTrade.setRejectDate(DateUtil.getCurrentLocalDateTime());  //当前时间
                settleTrade.setRejectPerformer(settleTrade.getOrgCode()); //银行直连机构号
                settleTrade.setRemark("银行驳回交易失败原因：" + BusiUtil.nvl(callBackBodyVo.getDescription(), EnumPaymentStatus.PAYMENT_FAIL_LOG.toString()));  //失败原因
                settleTrade.setCancelSend(EnumPaymentStatus.SETTLE_CANCEL_SEND.toString());

                // 更新跨境订单交易表
                log.info("更新跨境付汇订单状态为失败：" + settleTrade.getSettleId());
                settleTradeService.updateSettleTradeStatusRefidsLog(settleTrade, EnumPaymentStatus.PAYMENT_FAIL.toString()); //更新交易失败状态

                // 更新跨境订单明细表
                log.info("更新跨境付订单汇明细状态为未跨境付汇：" + settleTrade.getSettleId());
                settleTradeListService.updateSettleTradeListStatus(settleTrade.getSettleId(), "N");

            } else {
                //跨境付订交易状态报文未返回最终状态
                log.info("跨境付汇交易状态查询未返回最终状态：" + callBackBodyVo.getOrderNo());
            }
        }

        JSONObject jsonDate = new JSONObject();
        jsonDate.put(EnumJsonProperty.RES_PCSGRLT.toString(), EnumResultType.COM_RES_SUCCESS.getStatusCode());
        jsonDate.put(EnumJsonProperty.RES_FALRS.toString(), EnumResultType.COM_RES_SUCCESS.getMsg());
        result.setData(jsonDate);
        // 返回响应报文
        log.info("跨境付汇回调通知处理结束，返回报文：" + JSON.toJSONString(result));
        return result;
    }

    private String check(PaymentCallBackVo bankCallBackVo) {
        // 校验业务操作类型
        if (BusiUtil.isNull(bankCallBackVo.getOption())) {
            return "EE1027";
        }
        if (BusiUtil.isNull(bankCallBackVo.getSubArray())) {
            return "EE1028";
        }
        if (BusiUtil.isNotEquals(bankCallBackVo.getOption(), "1") &&
                BusiUtil.isNotEquals(bankCallBackVo.getOption(), "2") &&
                BusiUtil.isNotEquals(bankCallBackVo.getOption(), "3")) {
            return "EE1007";
        }
        return "";
    }

}
